package cn;

import java.io.IOException;
import java.util.Scanner;

import cn.drknt.lib.Data_type;
import cn.drknt.lib.Load_args;
import cn.wrapper.detector_wrapper;
import cn.wrapper.pthread_t;

public class detector extends detector_wrapper
{

static int coco_ids[] = {1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24,25,27,28,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,67,70,72,73,74,75,76,77,78,79,80,81,82,84,85,86,87,88,89,90};

static void train_detector(String datacfg, String cfgfile, String weightfile, int[] gpus, int ngpus, int clear) throws IOException, Exception
{
    list options = read_data_cfg(datacfg);
    String train_images = option_find_str(options, "train", "data/train.list");
    String backup_directory = option_find_str(options, "backup", "/backup/");

    srand(time(0));
    String base = basecfg(cfgfile);
    printf("%s\n", base);
    float avg_loss = -1;
    network[] nets = new network[ngpus];//calloc(ngpus, sizeof(network));

    srand(time(0));
    int seed = rand();
    int i;
    for(i = 0; i < ngpus; ++i){
        srand(seed);
//#ifdef GPU
//        cuda_set_device(gpus[i]);
//#endif
        nets[i] = load_network(cfgfile, weightfile, clear);
        nets[i].learning_rate *= ngpus;
    }
    srand(time(0));
    network net = nets[0];

    int imgs = net.batch * net.subdivisions * ngpus;
    printf("Learning Rate: %g, Momentum: %g, Decay: %g\n", net.learning_rate, net.momentum, net.decay);
    data train=new data(), buffer=new data();

    layer l = net.layers[net.n - 1];

    int classes = l.classes;
    float jitter = l.jitter;

//    list plist = get_paths(train_images);
//    //int N = plist.size;
//    String[] paths = (String[] )list_to_array(plist);
    String[] paths=get_paths2(train_images);
    Load_args args = get_base_args(net);
    args.coords = l.coords;
    args.paths = paths;
    args.n = imgs;
    args.m = paths.length;
    args.classes = classes;
    args.jitter = jitter;
    args.num_boxes = l.max_boxes;
    args.d = buffer;//&buffer;
    args.type = Data_type.DETECTION_DATA;
    //args.type = INSTANCE_DATA;
    args.threads = 1;//64;

    pthread_t load_thread = load_data(args);
    double time;
    int count = 0;
    //while(i*imgs < N*120){
    while(get_current_batch(net) < net.max_batches){
        if(l.random && count++%10 == 0){
            printf("Resizing\n");
            int dim = (rand() % 10 + 10) * 32;
            if (get_current_batch(net)+200 > net.max_batches) dim = 608;
            //int dim = (rand() % 4 + 16) * 32;
            printf("%d\n", dim);
            args.w = dim;
            args.h = dim;

            pthread_join(load_thread, 0);
//            train = buffer;
//            free_data(train);
            buffer=new data();//这是java的扔掉这批数据
            args.d = buffer;//让线程往args.d中加载数据时，即往buffer中加载图片数据
            load_thread = load_data(args);

            for(i = 0; i < ngpus; ++i){
                resize_network(nets[i], dim, dim);
            }
            net = nets[0];
        }
        time=what_time_is_it_now();
        pthread_join(load_thread, 0);
        train = buffer;
        buffer=new data();
		args.d = buffer;
        load_thread = load_data(args);

        /*
        int k;
        for(k = 0; k < l.max_boxes; ++k){
            box b = float_to_box(train.y.vals[10] + 1 + k*5);
            if(!b.x) break;
            printf("loaded: %f %f %f %f\n", b.x, b.y, b.w, b.h);
        }
        */
        /*
        int zz;
        for(zz = 0; zz < train.X.cols; ++zz){
            image im = float_to_image(net.w, net.h, 3, train.X.vals[zz]);
            int k;
            for(k = 0; k < l.max_boxes; ++k){
                box b = float_to_box(train.y.vals[zz] + k*5, 1);
                printf("%f %f %f %f\n", b.x, b.y, b.w, b.h);
                draw_bbox(im, b, 1, 1,0,0);
            }
            show_image(im, "truth11");
            cvWaitKey(0);
            save_image(im, "truth11");
        }
        */

        printf("Loaded: %f seconds\n", what_time_is_it_now()-time);

        time=what_time_is_it_now();
        float loss = 0;
//#ifdef GPU
//        if(ngpus == 1){
//            loss = train_network(net, train);
//        } else {
//            loss = train_networks(nets, ngpus, train, 4);
//        }
//#else
        System.err.println(String.format("begin train with train.data: X.rows=%d, X.cols=%d",train.X.rows,train.X.cols ));
        loss = train_network(net, train);
//#endif
        if (avg_loss < 0) avg_loss = loss;
        avg_loss = avg_loss*.9f + loss*.1f;

        i = get_current_batch(net);
        printf("%d: %f, %f avg, %f rate, %f seconds, %d images\n", get_current_batch(net), loss, avg_loss, get_current_rate(net), what_time_is_it_now()-time, i*imgs);
        if(i%100==0){
//#ifdef GPU
//            if(ngpus != 1) sync_nets(nets, ngpus, 0);
//#endif
//            char buff[256];
//            sprintf(buff, "%s/%s.backup", backup_directory, base);
        	String buff=String.format("%s/%s.backup", backup_directory, base);
            save_weights(net, buff);
        }
        if(i%10000==0 || (i < 1000 && i%100 == 0)){
//#ifdef GPU
//            if(ngpus != 1) sync_nets(nets, ngpus, 0);
//#endif
//            char buff[256];
//            sprintf(buff, "%s/%s_%d.weights", backup_directory, base, i);
        	String buff=String.format("%s/%s_%d.weights", backup_directory, base, i);
            save_weights(net, buff);
        }
        free_data(train);
    }
//#ifdef GPU
//    if(ngpus != 1) sync_nets(nets, ngpus, 0);
//#endif
//    char buff[256];
//    sprintf(buff, "%s/%s_final.weights", backup_directory, base);
    String buff=String.format("%s/%s_final.weights", backup_directory, base);
    save_weights(net, buff);
}


//static int get_coco_image_id(String filename)
//{
//    String p = strrchr(filename, '_');
//    return atoi(p+1);
//}
//
//static void print_cocos(FILE *fp, String image_path, box *boxes, float **probs, int num_boxes, int classes, int w, int h)
//{
//    int i, j;
//    int image_id = get_coco_image_id(image_path);
//    for(i = 0; i < num_boxes; ++i){
//        float xmin = boxes[i].x - boxes[i].w/2.;
//        float xmax = boxes[i].x + boxes[i].w/2.;
//        float ymin = boxes[i].y - boxes[i].h/2.;
//        float ymax = boxes[i].y + boxes[i].h/2.;
//
//        if (xmin < 0) xmin = 0;
//        if (ymin < 0) ymin = 0;
//        if (xmax > w) xmax = w;
//        if (ymax > h) ymax = h;
//
//        float bx = xmin;
//        float by = ymin;
//        float bw = xmax - xmin;
//        float bh = ymax - ymin;
//
//        for(j = 0; j < classes; ++j){
//            if (probs[i][j]) fprintf(fp, "{\"image_id\":%d, \"category_id\":%d, \"bbox\":[%f, %f, %f, %f], \"score\":%f},\n", image_id, coco_ids[j], bx, by, bw, bh, probs[i][j]);
//        }
//    }
//}

//void print_detector_detections(FILE **fps, String id, box *boxes, float **probs, int total, int classes, int w, int h)
//{
//    int i, j;
//    for(i = 0; i < total; ++i){
//        float xmin = boxes[i].x - boxes[i].w/2. + 1;
//        float xmax = boxes[i].x + boxes[i].w/2. + 1;
//        float ymin = boxes[i].y - boxes[i].h/2. + 1;
//        float ymax = boxes[i].y + boxes[i].h/2. + 1;
//
//        if (xmin < 1) xmin = 1;
//        if (ymin < 1) ymin = 1;
//        if (xmax > w) xmax = w;
//        if (ymax > h) ymax = h;
//
//        for(j = 0; j < classes; ++j){
//            if (probs[i][j]) fprintf(fps[j], "%s %f %f %f %f %f\n", id, probs[i][j],
//                    xmin, ymin, xmax, ymax);
//        }
//    }
//}
//
//void print_imagenet_detections(FILE *fp, int id, box *boxes, float **probs, int total, int classes, int w, int h)
//{
//    int i, j;
//    for(i = 0; i < total; ++i){
//        float xmin = boxes[i].x - boxes[i].w/2.;
//        float xmax = boxes[i].x + boxes[i].w/2.;
//        float ymin = boxes[i].y - boxes[i].h/2.;
//        float ymax = boxes[i].y + boxes[i].h/2.;
//
//        if (xmin < 0) xmin = 0;
//        if (ymin < 0) ymin = 0;
//        if (xmax > w) xmax = w;
//        if (ymax > h) ymax = h;
//
//        for(j = 0; j < classes; ++j){
//            int class = j;
//            if (probs[i][class]) fprintf(fp, "%d %d %f %f %f %f %f\n", id, j+1, probs[i][class],
//                    xmin, ymin, xmax, ymax);
//        }
//    }
//}
//
static void validate_detector_flip(String datacfg, String cfgfile, String weightfile, String outfile)
{
	System.err.println("not imple!!");
	exit(-1);
//    int j;
//    list options = read_data_cfg(datacfg);
//    String valid_images = option_find_str(options, "valid", "data/train.list");
//    String name_list = option_find_str(options, "names", "data/names.list");
//    String prefix = option_find_str(options, "results", "results");
//    String[] names = get_labels(name_list);
//    String mapf = option_find_str(options, "map", 0);
//    int[] map = 0;
//    if (mapf) map = read_map(mapf);
//
//    network net = load_network(cfgfile, weightfile, 0);
//    set_batch_network(net, 2);
//    fprintf(stderr, "Learning Rate: %g, Momentum: %g, Decay: %g\n", net.learning_rate, net.momentum, net.decay);
//    srand(time(0));
//
//    list *plist = get_paths(valid_images);
//    String[] paths = (String[] )list_to_array(plist);
//
//    layer l = net.layers[net.n-1];
//    int classes = l.classes;
//
//    char buff[1024];
//    String type = option_find_str(options, "eval", "voc");
//    FILE *fp = 0;
//    FILE **fps = 0;
//    int coco = 0;
//    int imagenet = 0;
//    if(0==strcmp(type, "coco")){
//        if(!outfile) outfile = "coco_results";
//        snprintf(buff, 1024, "%s/%s.json", prefix, outfile);
//        fp = fopen(buff, "w");
//        fprintf(fp, "[\n");
//        coco = 1;
//    } else if(0==strcmp(type, "imagenet")){
//        if(!outfile) outfile = "imagenet-detection";
//        snprintf(buff, 1024, "%s/%s.txt", prefix, outfile);
//        fp = fopen(buff, "w");
//        imagenet = 1;
//        classes = 200;
//    } else {
//        if(!outfile) outfile = "comp4_det_test_";
//        fps = calloc(classes, sizeof(FILE *));
//        for(j = 0; j < classes; ++j){
//            snprintf(buff, 1024, "%s/%s%s.txt", prefix, outfile, names[j]);
//            fps[j] = fopen(buff, "w");
//        }
//    }
//
//
//    box []boxes = calloc(l.w*l.h*l.n, sizeof(box));
//    float [][]probs = calloc(l.w*l.h*l.n, sizeof(float *));
//    for(j = 0; j < l.w*l.h*l.n; ++j) probs[j] = calloc(classes+1, sizeof(float *));
//
//    int m = plist.size;
//    int i=0;
//    int t;
//
//    float thresh = .005;
//    float nms = .45;
//
//    int nthreads = 4;
//    image *val = calloc(nthreads, sizeof(image));
//    image *val_resized = calloc(nthreads, sizeof(image));
//    image *buf = calloc(nthreads, sizeof(image));
//    image *buf_resized = calloc(nthreads, sizeof(image));
//    pthread_t *thr = calloc(nthreads, sizeof(pthread_t));
//
//    image input = make_image(net.w, net.h, net.c*2);
//
//    load_args args = {0};
//    args.w = net.w;
//    args.h = net.h;
//    //args.type = IMAGE_DATA;
//    args.type = LETTERBOX_DATA;
//
//    for(t = 0; t < nthreads; ++t){
//        args.path = paths[i+t];
//        args.im = &buf[t];
//        args.resized = &buf_resized[t];
//        thr[t] = load_data_in_thread(args);
//    }
//    double start = what_time_is_it_now();
//    for(i = nthreads; i < m+nthreads; i += nthreads){
//        fprintf(stderr, "%d\n", i);
//        for(t = 0; t < nthreads && i+t-nthreads < m; ++t){
//            pthread_join(thr[t], 0);
//            val[t] = buf[t];
//            val_resized[t] = buf_resized[t];
//        }
//        for(t = 0; t < nthreads && i+t < m; ++t){
//            args.path = paths[i+t];
//            args.im = &buf[t];
//            args.resized = &buf_resized[t];
//            thr[t] = load_data_in_thread(args);
//        }
//        for(t = 0; t < nthreads && i+t-nthreads < m; ++t){
//            String path = paths[i+t-nthreads];
//            String id = basecfg(path);
//            copy_cpu(net.w*net.h*net.c, val_resized[t].data, 1, input.data, 1);
//            flip_image(val_resized[t]);
//            copy_cpu(net.w*net.h*net.c, val_resized[t].data, 1, input.data + net.w*net.h*net.c, 1);
//
//            network_predict(net, input.data);
//            int w = val[t].w;
//            int h = val[t].h;
//            get_region_boxes(l, w, h, net.w, net.h, thresh, probs, boxes, 0, 0, map, .5, 0);
//            if (nms) do_nms_sort(boxes, probs, l.w*l.h*l.n, classes, nms);
//            if (coco){
//                print_cocos(fp, path, boxes, probs, l.w*l.h*l.n, classes, w, h);
//            } else if (imagenet){
//                print_imagenet_detections(fp, i+t-nthreads+1, boxes, probs, l.w*l.h*l.n, classes, w, h);
//            } else {
//                print_detector_detections(fps, id, boxes, probs, l.w*l.h*l.n, classes, w, h);
//            }
//            free(id);
//            free_image(val[t]);
//            free_image(val_resized[t]);
//        }
//    }
//    for(j = 0; j < classes; ++j){
//        if(fps) fclose(fps[j]);
//    }
//    if(coco){
//        fseek(fp, -2, SEEK_CUR); 
//        fprintf(fp, "\n]\n");
//        fclose(fp);
//    }
//    fprintf(stderr, "Total Detection Time: %f Seconds\n", what_time_is_it_now() - start);
}


static void validate_detector(String datacfg, String cfgfile, String weightfile, String outfile)
{
	System.err.println("not imple!!");
	exit(-1);
//    int j;
//    list *options = read_data_cfg(datacfg);
//    String valid_images = option_find_str(options, "valid", "data/train.list");
//    String name_list = option_find_str(options, "names", "data/names.list");
//    String prefix = option_find_str(options, "results", "results");
//    String[] names = get_labels(name_list);
//    String mapf = option_find_str(options, "map", 0);
//    int[] map = 0;
//    if (mapf) map = read_map(mapf);
//
//    network *net = load_network(cfgfile, weightfile, 0);
//    set_batch_network(net, 1);
//    fprintf(stderr, "Learning Rate: %g, Momentum: %g, Decay: %g\n", net.learning_rate, net.momentum, net.decay);
//    srand(time(0));
//
//    list *plist = get_paths(valid_images);
//    String[] paths = (String[] )list_to_array(plist);
//
//    layer l = net.layers[net.n-1];
//    int classes = l.classes;
//
//    char buff[1024];
//    String type = option_find_str(options, "eval", "voc");
//    FILE *fp = 0;
//    FILE **fps = 0;
//    int coco = 0;
//    int imagenet = 0;
//    if(0==strcmp(type, "coco")){
//        if(!outfile) outfile = "coco_results";
//        snprintf(buff, 1024, "%s/%s.json", prefix, outfile);
//        fp = fopen(buff, "w");
//        fprintf(fp, "[\n");
//        coco = 1;
//    } else if(0==strcmp(type, "imagenet")){
//        if(!outfile) outfile = "imagenet-detection";
//        snprintf(buff, 1024, "%s/%s.txt", prefix, outfile);
//        fp = fopen(buff, "w");
//        imagenet = 1;
//        classes = 200;
//    } else {
//        if(!outfile) outfile = "comp4_det_test_";
//        fps = calloc(classes, sizeof(FILE *));
//        for(j = 0; j < classes; ++j){
//            snprintf(buff, 1024, "%s/%s%s.txt", prefix, outfile, names[j]);
//            fps[j] = fopen(buff, "w");
//        }
//    }
//
//
//    box *boxes = calloc(l.w*l.h*l.n, sizeof(box));
//    float **probs = calloc(l.w*l.h*l.n, sizeof(float *));
//    for(j = 0; j < l.w*l.h*l.n; ++j) probs[j] = calloc(classes+1, sizeof(float *));
//
//    int m = plist.size;
//    int i=0;
//    int t;
//
//    float thresh = .005;
//    float nms = .45;
//
//    int nthreads = 4;
//    image *val = calloc(nthreads, sizeof(image));
//    image *val_resized = calloc(nthreads, sizeof(image));
//    image *buf = calloc(nthreads, sizeof(image));
//    image *buf_resized = calloc(nthreads, sizeof(image));
//    pthread_t *thr = calloc(nthreads, sizeof(pthread_t));
//
//    load_args args = {0};
//    args.w = net.w;
//    args.h = net.h;
//    //args.type = IMAGE_DATA;
//    args.type = LETTERBOX_DATA;
//
//    for(t = 0; t < nthreads; ++t){
//        args.path = paths[i+t];
//        args.im = &buf[t];
//        args.resized = &buf_resized[t];
//        thr[t] = load_data_in_thread(args);
//    }
//    double start = what_time_is_it_now();
//    for(i = nthreads; i < m+nthreads; i += nthreads){
//        fprintf(stderr, "%d\n", i);
//        for(t = 0; t < nthreads && i+t-nthreads < m; ++t){
//            pthread_join(thr[t], 0);
//            val[t] = buf[t];
//            val_resized[t] = buf_resized[t];
//        }
//        for(t = 0; t < nthreads && i+t < m; ++t){
//            args.path = paths[i+t];
//            args.im = &buf[t];
//            args.resized = &buf_resized[t];
//            thr[t] = load_data_in_thread(args);
//        }
//        for(t = 0; t < nthreads && i+t-nthreads < m; ++t){
//            String path = paths[i+t-nthreads];
//            String id = basecfg(path);
//            float *X = val_resized[t].data;
//            network_predict(net, X);
//            int w = val[t].w;
//            int h = val[t].h;
//            get_region_boxes(l, w, h, net.w, net.h, thresh, probs, boxes, 0, 0, map, .5, 0);
//            if (nms) do_nms_sort(boxes, probs, l.w*l.h*l.n, classes, nms);
//            if (coco){
//                print_cocos(fp, path, boxes, probs, l.w*l.h*l.n, classes, w, h);
//            } else if (imagenet){
//                print_imagenet_detections(fp, i+t-nthreads+1, boxes, probs, l.w*l.h*l.n, classes, w, h);
//            } else {
//                print_detector_detections(fps, id, boxes, probs, l.w*l.h*l.n, classes, w, h);
//            }
//            free(id);
//            free_image(val[t]);
//            free_image(val_resized[t]);
//        }
//    }
//    for(j = 0; j < classes; ++j){
//        if(fps) fclose(fps[j]);
//    }
//    if(coco){
//        fseek(fp, -2, SEEK_CUR); 
//        fprintf(fp, "\n]\n");
//        fclose(fp);
//    }
//    fprintf(stderr, "Total Detection Time: %f Seconds\n", what_time_is_it_now() - start);
}
//
static void validate_detector_recall(String cfgfile, String weightfile)
{
//    network *net = load_network(cfgfile, weightfile, 0);
//    set_batch_network(net, 1);
//    fprintf(stderr, "Learning Rate: %g, Momentum: %g, Decay: %g\n", net.learning_rate, net.momentum, net.decay);
//    srand(time(0));
//
//    list *plist = get_paths("data/coco_val_5k.list");
//    String[] paths = (String[] )list_to_array(plist);
//
//    layer l = net.layers[net.n-1];
//    int classes = l.classes;
//
//    int j, k;
//    box *boxes = calloc(l.w*l.h*l.n, sizeof(box));
//    float **probs = calloc(l.w*l.h*l.n, sizeof(float *));
//    for(j = 0; j < l.w*l.h*l.n; ++j) probs[j] = calloc(classes+1, sizeof(float *));
//
//    int m = plist.size;
//    int i=0;
//
//    float thresh = .001;
//    float iou_thresh = .5;
//    float nms = .4;
//
//    int total = 0;
//    int correct = 0;
//    int proposals = 0;
//    float avg_iou = 0;
//
//    for(i = 0; i < m; ++i){
//        String path = paths[i];
//        image orig = load_image_color(path, 0, 0);
//        image sized = resize_image(orig, net.w, net.h);
//        String id = basecfg(path);
//        network_predict(net, sized.data);
//        get_region_boxes(l, sized.w, sized.h, net.w, net.h, thresh, probs, boxes, 0, 1, 0, .5, 1);
//        if (nms) do_nms(boxes, probs, l.w*l.h*l.n, 1, nms);
//
//        char labelpath[4096];
//        find_replace(path, "images", "labels", labelpath);
//        find_replace(labelpath, "JPEGImages", "labels", labelpath);
//        find_replace(labelpath, ".jpg", ".txt", labelpath);
//        find_replace(labelpath, ".JPEG", ".txt", labelpath);
//
//        int num_labels = 0;
//        box_label *truth = read_boxes(labelpath, &num_labels);
//        for(k = 0; k < l.w*l.h*l.n; ++k){
//            if(probs[k][0] > thresh){
//                ++proposals;
//            }
//        }
//        for (j = 0; j < num_labels; ++j) {
//            ++total;
//            box t = {truth[j].x, truth[j].y, truth[j].w, truth[j].h};
//            float best_iou = 0;
//            for(k = 0; k < l.w*l.h*l.n; ++k){
//                float iou = box_iou(boxes[k], t);
//                if(probs[k][0] > thresh && iou > best_iou){
//                    best_iou = iou;
//                }
//            }
//            avg_iou += best_iou;
//            if(best_iou > iou_thresh){
//                ++correct;
//            }
//        }
//
//        fprintf(stderr, "%5d %5d %5d\tRPs/Img: %.2f\tIOU: %.2f%%\tRecall:%.2f%%\n", i, correct, total, (float)proposals/(i+1), avg_iou*100/total, 100.*correct/total);
//        free(id);
//        free_image(orig);
//        free_image(sized);
//    }
}

static void test_detector(String datacfg, String cfgfile, String weightfile, String filename, float thresh, float hier_thresh, String outfile, int fullscreen) throws IOException, Exception
{

    list options = read_data_cfg(datacfg);
    String name_list = option_find_str(options, "names", "data/names.list");
    String[] names = get_labels(name_list);

    image [][]alphabet = load_alphabet();
    network net = load_network(cfgfile, weightfile, 0);
    set_batch_network(net, 1);
    srand(2222222);
    double time;
//    char buff[256];
    String input = null;//buff;
    int j;
    float nms=.3f;
    while(true/*1*/){
        if(filename!=null){
        	input=filename.trim();//strncpy(input, filename, 256);
        } else {
            printf("Enter Image Path: ");
//            fflush(stdout);
//            input = fgets(input, 256, stdin);
//            if(!input) return;
//            strtok(input, "\n");
            Scanner in = new Scanner(System.in);
            input=in.nextLine();
            if(null==input) return;
        }
        image im = load_image_color(input,0,0);
        image sized = letterbox_image(im, net.w, net.h);
        //image sized = resize_image(im, net.w, net.h);
        //image sized2 = resize_max(im, net.w);
        //image sized = crop_image(sized2, -((net.w - sized2.w)/2), -((net.h - sized2.h)/2), net.w, net.h);
        //resize_network(net, sized.w, sized.h);
        layer l = net.layers[net.n-1];

        box []boxes = new box[l.w*l.h*l.n];//calloc(l.w*l.h*l.n, sizeof(box));
        float [][]probs = new float[l.w*l.h*l.n][];//calloc(l.w*l.h*l.n, sizeof(float *));
        for(j = 0; j < l.w*l.h*l.n; ++j) probs[j] = calloc(l.classes + 1, 1/*sizeof(float*)*/);
        float [][]masks = null;
        if (l.coords > 4){
            masks = new float[l.w*l.h*l.n][];//calloc(l.w*l.h*l.n, sizeof(float*));
            for(j = 0; j < l.w*l.h*l.n; ++j) masks[j] = calloc(l.coords-4, 1/*sizeof(float *)*/);
        }

        float []X = sized.data;
        time=what_time_is_it_now();
        network_predict(net, X);
        printf("%s: Predicted in %f seconds.\n", input, what_time_is_it_now()-time);
        get_region_boxes(l, im.w, im.h, net.w, net.h, thresh, probs, boxes, masks, 0, 0, hier_thresh, 1);
        //if (nms) do_nms_obj(boxes, probs, l.w*l.h*l.n, l.classes, nms);
        if (nms!=0) do_nms_sort(boxes, probs, l.w*l.h*l.n, l.classes, nms);
        draw_detections(im, l.w*l.h*l.n, thresh, boxes, probs, masks, names, alphabet, l.classes);
        if(outfile!=null){
            save_image(im, outfile);
        }
        else{
            save_image(im, "predictions");
//#ifdef OPENCV
//            cvNamedWindow("predictions", CV_WINDOW_NORMAL); 
//            if(fullscreen){
//                cvSetWindowProperty("predictions", CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
//            }
//            show_image(im, "predictions");
//            cvWaitKey(0);
//            cvDestroyAllWindows();
//#endif
        }

//        free_image(im);
//        free_image(sized);
//        free(boxes);
//        free_ptrs((void **)probs, l.w*l.h*l.n);
        if (filename!=null) break;
    }
}

public static void run_detector(int argc, String[] argv) throws IOException, Exception
{
    String prefix = find_char_arg(argc, argv, "-prefix", 0);
    float thresh = find_float_arg(argc, argv, "-thresh", .24);
    float hier_thresh = find_float_arg(argc, argv, "-hier", .5);
    int cam_index = find_int_arg(argc, argv, "-c", 0);
    int frame_skip = find_int_arg(argc, argv, "-s", 0);
    int avg = find_int_arg(argc, argv, "-avg", 3);
    if(argc < 4){
        fprintf(stderr, "usage: %s %s [train/test/valid] [cfg] [weights (optional)]\n", argv[0], argv[1]);
        return;
    }
    String gpu_list = find_char_arg(argc, argv, "-gpus", 0);
    String outfile = find_char_arg(argc, argv, "-out", 0);
    int[] gpus = null;
    int gpu = 0;
    int ngpus = 0;
    if(gpu_list!=null){
        printf("%s\n", gpu_list);
        int len = strlen(gpu_list);
        ngpus = 1;
        int i;
        for(i = 0; i < len; ++i){
            if (gpu_list.charAt(i)/*[i]*/ == ',') ++ngpus;
        }
        gpus = callocInt(ngpus, 1/*sizeof(int)*/);
        for(i = 0; i < ngpus; ++i){
            gpus[i] = atoi(gpu_list);
            gpu_list = gpu_list.substring(strchr(gpu_list, ',')+1);//strchr(gpu_list, ',')+1;
        }
    } else {
        gpu = gpu_index;
        gpus = new int[1];gpus[0]=gpu;//gpus = &gpu;
        ngpus = 1;
    }

    int clear = find_arg(argc, argv, "-clear");
    int fullscreen = find_arg(argc, argv, "-fullscreen");
    int width = find_int_arg(argc, argv, "-w", 0);
    int height = find_int_arg(argc, argv, "-h", 0);
    int fps = find_int_arg(argc, argv, "-fps", 0);

    String datacfg = argv[3];
    String cfg = argv[4];
    String weights = (argc > 5) ? argv[5] : null;
    String filename = (argc > 6) ? argv[6]: null;
    if(0==strcmp(argv[2], "test")) test_detector(datacfg, cfg, weights, filename, thresh, hier_thresh, outfile, fullscreen);
    else if(0==strcmp(argv[2], "train")) train_detector(datacfg, cfg, weights, gpus, ngpus, clear);
    else if(0==strcmp(argv[2], "valid")) validate_detector(datacfg, cfg, weights, outfile);
    else if(0==strcmp(argv[2], "valid2")) validate_detector_flip(datacfg, cfg, weights, outfile);
    else if(0==strcmp(argv[2], "recall")) validate_detector_recall(cfg, weights);
    else if(0==strcmp(argv[2], "demo")) {
//        list options = read_data_cfg(datacfg);
//        int classes = option_find_int(options, "classes", 20);
//        String name_list = option_find_str(options, "names", "data/names.list");
//        String[] names = get_labels(name_list);
//        demo(cfg, weights, thresh, cam_index, filename, names, classes, frame_skip, prefix, avg, hier_thresh, width, height, fps, fullscreen);
    	System.err.println("demo not imple...");
    }
}

}